home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / lib / stdio / sfmt.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  6KB  |  333 lines

  1.  
  2. /*
  3.  *  SFMT.C    *scanf()
  4.  *
  5.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  6.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  7.  *    DICE-LICENSE.TXT.
  8.  *
  9.  *  func format same as fgetc: func(desc)
  10.  *  unfunc format same as ungetc: func(c,desc)
  11.  */
  12.  
  13. #include <stdarg.h>
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <lib/misc.h>
  17.  
  18. #define F_SHORT     32
  19. #define F_LONG        64
  20. #define F_DLONG     128
  21.  
  22. static char buf2[256];
  23.  
  24. int
  25. _sfmt(ctl, va, func, unfunc, desc, pcnt)
  26. unsigned char *ctl;
  27. va_list va;
  28. int (*func)(void *);
  29. int (*unfunc)(int, void *);
  30. int *pcnt;
  31. void *desc;
  32. {
  33.     short flags;
  34.     short v;
  35.     short i1;
  36.     int nscanned = 0;
  37.     void *stor;
  38.  
  39.     *pcnt = 0;
  40.     v = (*func)(desc);
  41.     for (;;) {
  42.     while (*ctl && *ctl != '%') {
  43.         if (*ctl == ' ' || *ctl == '\t') {
  44.         if (v != ' ' && v != '\t' && v != '\n')
  45.             goto done;
  46.         while (v == ' ' || v == '\t') {
  47.             v = (*func)(desc);
  48.             ++nscanned;
  49.         }
  50.         while (*ctl == ' ' || *ctl == '\t')
  51.             ++ctl;
  52.         } else {
  53.         if (v != *ctl)
  54.             goto done;
  55.         v = (*func)(desc);
  56.         ++nscanned;
  57.         ++ctl;
  58.         }
  59.         if (v == 0)
  60.         goto done;
  61.     }
  62.     if (*ctl++ == 0)
  63.         goto done;
  64.     if (*ctl == '%') {      /*  match a %   */
  65.         if (v != '%')
  66.         goto done;
  67.         v = (*func)(desc);
  68.         ++nscanned;
  69.         ++ctl;
  70.         continue;
  71.     }
  72.  
  73.     /*
  74.      *  %[flags][width]c
  75.      */
  76.  
  77.     if (*ctl == '*') {
  78.         stor = NULL;
  79.         ++ctl;
  80.     } else {
  81.         stor = va_arg(va, void *);
  82.     }
  83.     i1 = -1;
  84.     if (*ctl >= '0' && *ctl <= '9') {
  85.         char c = *ctl;
  86.         i1 = 0;
  87.         while (c >= '0' && c <= '9') {
  88.         i1 = i1 * 10 + (c - '0');
  89.         c = *++ctl;
  90.         }
  91.     }
  92.     flags = 0;
  93.     for (;;) {
  94.         char c = *ctl;
  95.         if (c == 'h') {
  96.         ++ctl;
  97.         flags |= F_SHORT;   /*    only if sizeof(int) != 4 */
  98.         continue;
  99.         }
  100.         if (c == 'l') {
  101.         ++ctl;
  102.         flags |= F_LONG;
  103.         continue;
  104.         }
  105.         if (c == 'L') {
  106.         ++ctl;
  107.         flags |= F_DLONG;
  108.         continue;
  109.         }
  110.         break;
  111.     }
  112.     if (*ctl == 'n') {
  113.         if (stor) {
  114.         if (flags & F_SHORT)
  115.             *(short *)stor = nscanned;
  116.         else
  117.             *(int *)stor = nscanned;
  118.         stor = NULL;    /* don't count %n in retval */
  119.         }
  120.     } else {
  121.         nscanned = _sfmtone(ctl, &v, stor, func, desc, flags, i1, nscanned);
  122.     }
  123.     if (*ctl == '[') {
  124.         ++ctl;
  125.         if (*ctl == '^')
  126.         ++ctl;
  127.         if (*ctl == ']')
  128.         ++ctl;
  129.         while(*ctl&&(*ctl != ']')&&(*ctl != ' ')&&(*ctl != '\t')&&(*ctl != '\n'))
  130.         ++ctl;
  131.         if (*ctl == 0)
  132.         --ctl;
  133.     }
  134.     ++ctl;
  135.     if (nscanned < 0)
  136.         break;
  137.     if (stor)
  138.         ++*pcnt;
  139.     }
  140. done:
  141.     if (v != EOF)
  142.     (*unfunc)(v, desc);
  143.  
  144.     if (nscanned < 0 && *pcnt == 0)
  145.     return(EOF);
  146.     return(0);
  147. }
  148.  
  149. _sfmtone(ctl, pv, stor, func, desc, flags, i1, nscanned)
  150. char *ctl;    /*  conversion specifier    */
  151. short *pv;    /*  last read value        */
  152. void *stor;    /*  pointer into storage    */
  153. int (*func)(void *);  /*  fgetc type function      */
  154. void *desc;    /*  stdio/custom descriptor */
  155. short flags;    /*  conversion flags        */
  156. short i1;    /*  maximum field width     */
  157. short nscanned;
  158. {
  159.     short v = *pv;
  160.     int len = 0;
  161.     char buf[32];
  162.     char *ptr = buf;
  163.     char c = *ctl;
  164.  
  165.     if (c != 'c') {     /*  %c is a special case */
  166.     while (v == ' ' || v == '\t' || v == '\n') {
  167.         v = (*func)(desc);
  168.         ++nscanned;
  169.     }
  170.     }
  171.  
  172.     if (v == 0 || v == EOF)
  173.     return(EOF);
  174.  
  175.     switch(c) {
  176.     case 'c':
  177.     if (i1 == -1)
  178.         i1 = 1;
  179.     while (v != EOF && v != '\n' && i1) {
  180.         if (stor)
  181.         *(char *)stor = v;
  182.         v = (*func)(desc);
  183.         ++nscanned;
  184.         if (stor)
  185.         stor = (void *)((char *)stor + 1);
  186.         --i1;
  187.     }
  188.     break;
  189.     case 'p':   /*  0x format   */
  190.     if (i1 < 0)
  191.         i1 = 8;
  192.     case 'x':
  193.     case 'X':
  194.     case 'o':
  195.     case 'i':
  196.     case 'd':
  197.     case 'u':
  198.     {
  199.         long n = 0;
  200.         short neg = 0;
  201.         short base = 10;
  202.         short b1 = i1;
  203.  
  204.         if (i1 && v == '-') {
  205.         neg = 1;
  206.         v = (*func)(desc);
  207.         ++nscanned;
  208.         --i1;
  209.         }
  210.         if (c == 'o')
  211.         base = 8;
  212.         if (c == 'x' || c == 'X' || c == 'p') {
  213.         base = 16;
  214.         if (i1 && v == '0') {
  215.             v = (*func)(desc);
  216.             --i1;
  217.             ++nscanned;
  218.             if (i1 && v == 'x' || v == 'X') {
  219.             --i1;
  220.             v = (*func)(desc);
  221.             ++nscanned;
  222.             }
  223.         }
  224.         }
  225.         if (i1 && c == 'i' && v == '0') {
  226.         base = 8;
  227.         v = (*func)(desc);
  228.         --i1;
  229.         ++nscanned;
  230.         if (i1 && v == 'x' || v == 'X') {
  231.             base = 16;
  232.             v = (*func)(desc);
  233.             --i1;
  234.             ++nscanned;
  235.         }
  236.         }
  237.         while (i1) {
  238.         short vv;
  239.  
  240.         if (v >= '0' && v <= '9')
  241.             vv = v - '0';
  242.         else if (v >= 'a' && v <= 'z')
  243.             vv = v - ('a' - 10);
  244.         else if (v >= 'A' && v <= 'Z')
  245.             vv = v - ('A' - 10);
  246.         else
  247.             break;
  248.         if (vv >= base)
  249.             break;
  250.         n = n * base + vv;
  251.         v = (*func)(desc);
  252.         ++nscanned;
  253.         --i1;
  254.         }
  255.         if (b1 == i1)
  256.         return(EOF);
  257.         if (neg)
  258.         n = -n;
  259.         if (stor) {
  260.         if (flags & F_SHORT)
  261.             *(short *)stor = n;
  262.         else
  263.             *(int *)stor = n;
  264.         }
  265.     }
  266.     break;
  267. #ifdef MATH_SFMT
  268. #include <math/sfmt.c>
  269. #else
  270.     case 'e':
  271.     case 'E':
  272.     case 'f':
  273.     case 'g':
  274.     case 'G':
  275.     fprintf(stderr, "*scanf: %%e,E,f,g,G use -lm (mathlib)\n");
  276.     break;
  277. #endif
  278.     case 's':
  279.     while (i1 && v != ' ' && v != '\t' && v != '\n' && v != EOF) {
  280.         if (stor)
  281.         *(char *)stor = v;
  282.         v = (*func)(desc);
  283.         ++nscanned;
  284.         if (stor)
  285.         stor = (void *)((char *)stor + 1);
  286.         --i1;
  287.     }
  288.     if (stor)
  289.         *(char *)stor = 0;
  290.     break;
  291.     case '[':
  292.     {
  293.         char vax;
  294.         short i;
  295.  
  296.         ++ctl;
  297.         if (*ctl == '^') {
  298.         ++ctl;
  299.         setmem(buf2, 256, 1);
  300.         vax = 0;
  301.         } else {
  302.         setmem(buf2, 256, 0);
  303.         vax = 1;
  304.         }
  305.         if (*ctl == ']') {
  306.         ++ctl;
  307.         buf2[']'] = vax;
  308.         }
  309.         while ((i = (unsigned char)*ctl)&&(i != ']')&&(i != '\t')&&(i != '\n')) {
  310.         buf2[i] = vax;
  311.         ++ctl;
  312.         }
  313.     }
  314.     while (i1 && v != EOF && buf2[v]) {
  315.         if (stor)
  316.         *(char *)stor = v;
  317.         v = (*func)(desc);
  318.         ++nscanned;
  319.         if (stor)
  320.         stor = (void *)((char *)stor + 1);
  321.         --i1;
  322.     }
  323.     if (stor)
  324.         *(char *)stor = 0;
  325.     break;
  326.     default:
  327.     return(-2);
  328.     }
  329.     *pv = v;
  330.     return(nscanned);
  331. }
  332.  
  333.